# ui.py
import psutil
import platform
import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
from typing import List, Dict, Any, Optional, Callable
import os
import json
from datetime import datetime
import hashlib
from concurrent.futures import ThreadPoolExecutor
import threading
import subprocess
from pathlib import Path

from code.config import CleanerConfig
from code.manager import CleanManager
from code.scan_results_ui import EnhancedScanResultsWindow


class EnhancedCleanUI(tk.Tk):
    """增强版清理工具UI，提供更好的用户体验和功能"""
    
    def __init__(self):
        super().__init__()
        self.title("智能清理工具")
        self.geometry("800x700")
        self.config(padx=20, pady=20)

        # 初始化配置对象
        self.config = CleanerConfig()
        
        # 设置图标
        try:
            self.iconbitmap("cleaner.ico")
        except:
            pass

        # 核心参数存储
        self.custom_dirs = []
        self.system_type = None
        self.do_clean = False
        self.is_scanning = False
        self.scan_paused = False
        self.full_scan = tk.BooleanVar(value=False)
        self.duplicate_result_file = tk.StringVar()  # 存储重复文件扫描结果路径
        self.hash_algorithm_var = tk.StringVar(value='md5')
        self.hash_desc_var = tk.StringVar()
        # 添加这行代码初始化fast_mode_var
        self.fast_mode_var = tk.BooleanVar(value=False)  # 新增这行
        
        # 创建UI组件
        self.create_widgets()
        
        # 加载上次使用的配置
        self.load_settings()

    def update_log(self, message: str):
        """在日志区域显示扫描状态"""
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, f"[操作日志] {message}\n")
        self.log_text.config(state=tk.DISABLED)
        self.log_text.see(tk.END)
    
    def create_widgets(self):
        # 创建主框架
        main_frame = ttk.Frame(self)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 左侧控制面板
        control_frame = ttk.LabelFrame(main_frame, text="清理设置")
        control_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 清理类型选择
        ttk.Label(control_frame, text="清理类型:").pack(anchor=tk.W, padx=5, pady=5)
        
        # ====== 重复文件设置区域 ======
        duplicate_frame = ttk.LabelFrame(control_frame, text="重复文件设置")
        duplicate_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 重复文件复选框
        self.duplicate_var = tk.IntVar(value=1)
        duplicate_check = ttk.Checkbutton(
            duplicate_frame, 
            text="扫描重复文件", 
            variable=self.duplicate_var,
            command=self.toggle_duplicate_settings
        )
        duplicate_check.pack(anchor=tk.W, padx=5, pady=2)
        
        # 哈希算法设置
        hash_frame = ttk.Frame(duplicate_frame)
        hash_frame.pack(fill=tk.X, padx=15, pady=2)
        
        ttk.Label(hash_frame, text="哈希算法:").pack(side=tk.LEFT, padx=5)
        self.algo_combobox = ttk.Combobox(
            hash_frame, 
            textvariable=self.hash_algorithm_var,
            values=list(CleanerConfig.get_hash_algorithms().keys()),
            state="readonly",
            width=10
        )
        self.algo_combobox.pack(side=tk.LEFT, padx=5)
        self.algo_combobox.bind("<<ComboboxSelected>>", self.update_hash_description)
        
        # 算法描述标签
        self.hash_desc_label = ttk.Label(hash_frame, textvariable=self.hash_desc_var, width=30)
        self.hash_desc_label.pack(side=tk.LEFT, padx=5)

        # 快速扫描模式选项（放在重复文件设置区域内）
        fast_mode_frame = ttk.Frame(duplicate_frame)
        fast_mode_frame.pack(fill=tk.X, padx=15, pady=2)
        
        self.fast_mode_check = ttk.Checkbutton(
            fast_mode_frame, 
            text="快速扫描模式（使用文件属性哈希）", 
            variable=self.fast_mode_var
        )
        self.fast_mode_check.pack(side=tk.LEFT, padx=5)
        
        # 扫描重复文件夹设置
        folder_frame = ttk.Frame(duplicate_frame)
        folder_frame.pack(fill=tk.X, padx=15, pady=2)
        
        self.check_folders = tk.BooleanVar(value=False)
        self.folder_check = ttk.Checkbutton(
            folder_frame, 
            text="扫描重复文件夹", 
            variable=self.check_folders
        )
        self.folder_check.pack(side=tk.LEFT, padx=5)
        
        depth_frame = ttk.Frame(folder_frame)
        depth_frame.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(depth_frame, text="深度:").pack(side=tk.LEFT)
        self.folder_depth = tk.IntVar(value=3)
        self.depth_entry = ttk.Entry(depth_frame, textvariable=self.folder_depth, width=5)
        self.depth_entry.pack(side=tk.LEFT, padx=5)

        
        # 增加：重复文件扫描结果文件输入
        result_file_frame = ttk.Frame(duplicate_frame)
        result_file_frame.pack(fill=tk.X, padx=15, pady=2)
        
        ttk.Label(result_file_frame, text="重复文件结果:").pack(side=tk.LEFT, padx=5)
        self.duplicate_result_entry = ttk.Entry(result_file_frame, textvariable=self.duplicate_result_file)
        self.duplicate_result_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        ttk.Button(result_file_frame, text="浏览", command=self.browse_duplicate_result_file).pack(side=tk.LEFT, padx=5)
        ttk.Button(result_file_frame, text="清除", command=self.clear_duplicate_result).pack(side=tk.LEFT, padx=5)
        
        # ====== 软件包设置区域 ======
        package_frame = ttk.LabelFrame(control_frame, text="软件包设置")
        package_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 软件包复选框
        self.package_var = tk.IntVar(value=1)
        package_check = ttk.Checkbutton(
            package_frame, 
            text="扫描软件包", 
            variable=self.package_var,
            command=self.toggle_package_settings
        )
        package_check.pack(anchor=tk.W, padx=5, pady=2)
        
        # 软件包扩展名设置
        ext_frame = ttk.Frame(package_frame)
        ext_frame.pack(fill=tk.X, padx=15, pady=2)
        
        ttk.Label(ext_frame, text="扩展名:").pack(side=tk.LEFT, padx=5)
        self.ext_entry = ttk.Entry(ext_frame)
        self.ext_entry.insert(0, "exe,msi,zip,rar,7z,iso,dmg,pkg,deb,rpm")
        self.ext_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        # ====== 系统设置区域 ======
        system_frame = ttk.LabelFrame(control_frame, text="系统设置")
        system_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 系统类型选择
        ttk.Label(system_frame, text="操作系统:").pack(anchor=tk.W, padx=5, pady=2)
        self.system_combobox = ttk.Combobox(system_frame, values=["自动检测", "Windows", "Linux", "macOS"])
        self.system_combobox.set("自动检测")
        self.system_combobox.pack(fill=tk.X, padx=5, pady=2)
        
        # 全盘扫描选项
        ttk.Checkbutton(
            system_frame, 
            text="全盘扫描",
            variable=self.full_scan,
            command=self.toggle_full_scan
        ).pack(anchor=tk.W, padx=5, pady=2)
        
        # ====== 目录设置区域 ======
        dir_frame = ttk.LabelFrame(control_frame, text="扫描目录设置")
        dir_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 自定义目录管理
        ttk.Label(dir_frame, text="扫描目录:").pack(anchor=tk.W, padx=5, pady=2)
        
        dir_list_frame = ttk.Frame(dir_frame)
        dir_list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=2)
        
        self.dir_listbox = tk.Listbox(dir_list_frame, height=5)
        self.dir_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        dir_button_frame = ttk.Frame(dir_list_frame)
        dir_button_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5)
        
        self.add_dir_button = ttk.Button(dir_button_frame, text="添加", command=self.add_directory)
        self.add_dir_button.pack(fill=tk.X, pady=2)
        self.remove_dir_button = ttk.Button(dir_button_frame, text="删除", command=self.remove_directory)
        self.remove_dir_button.pack(fill=tk.X, pady=2)
        self.add_temp_button = ttk.Button(dir_button_frame, text="添加系统临时目录", command=self.add_system_temp_dirs)
        self.add_temp_button.pack(fill=tk.X, pady=2)
        
        # ====== 高级过滤设置 ======
        filter_frame = ttk.LabelFrame(control_frame, text="高级目录过滤")
        filter_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(filter_frame, text="包含关键字（逗号分隔）:").pack(anchor=tk.W, padx=5, pady=2)
        self.keyword_entry = ttk.Entry(filter_frame)
        self.keyword_entry.pack(fill=tk.X, padx=5, pady=2)
        self.keyword_entry.insert(0, "install,setup,downloads")

        ttk.Label(filter_frame, text="排除文件后缀（逗号分隔）:").pack(anchor=tk.W, padx=5, pady=2)
        self.exclude_ext_entry = ttk.Entry(filter_frame)
        self.exclude_ext_entry.pack(fill=tk.X, padx=5, pady=2)
        
        logic_frame = ttk.Frame(filter_frame)
        logic_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(logic_frame, text="逻辑关系:").pack(side=tk.LEFT, padx=5)
        self.logic_combobox = ttk.Combobox(logic_frame, values=["或 (OR)", "与 (AND)"], width=10)
        self.logic_combobox.set("或 (OR)")
        self.logic_combobox.pack(side=tk.LEFT, padx=5)
        
        self.recursive_var = tk.BooleanVar(value=self.config.recursive)
        self.recursive_check = ttk.Checkbutton(filter_frame, text="递归扫描子目录", variable=self.recursive_var)
        self.recursive_check.pack(anchor=tk.W, padx=5)
        
        # 应用过滤设置按钮
        self.apply_filter_button = ttk.Button(filter_frame, text="应用过滤", command=self.apply_filter_settings)
        self.apply_filter_button.pack(side=tk.RIGHT, padx=5)
        
        # ====== 右侧信息和操作区域 ======
        info_frame = ttk.LabelFrame(main_frame, text="扫描信息")
        info_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 扫描进度条
        ttk.Label(info_frame, text="扫描进度:").pack(anchor=tk.W, padx=5, pady=5)
        self.progress_bar = ttk.Progressbar(info_frame, orient=tk.HORIZONTAL, length=300, mode='determinate')
        self.progress_bar.pack(fill=tk.X, padx=5, pady=5)
        
        # 操作按钮
        button_frame = ttk.Frame(info_frame)
        button_frame.pack(fill=tk.X, padx=5, pady=10)
        
        self.start_button = ttk.Button(button_frame, text="开始扫描", command=self.start_scan)
        self.start_button.pack(side=tk.LEFT, padx=5)
        
        self.stop_button = ttk.Button(button_frame, text="停止扫描", command=self.stop_scan, state=tk.DISABLED)
        self.stop_button.pack(side=tk.LEFT, padx=5)
        
        self.pause_button = ttk.Button(button_frame, text="暂停", command=self.toggle_pause, state=tk.DISABLED)
        self.pause_button.pack(side=tk.LEFT, padx=5)
        
        self.show_results_button = ttk.Button(button_frame, text="查看扫描结果", command=self.show_scan_results, state=tk.DISABLED)
        self.show_results_button.pack(side=tk.LEFT, padx=5)
        
        self.load_results_button = ttk.Button(button_frame, text="加载历史结果", command=self.load_scan_results)
        self.load_results_button.pack(side=tk.LEFT, padx=5)
        
        self.clean_button = ttk.Button(button_frame, text="执行清理", command=self.start_clean, state=tk.DISABLED)
        self.clean_button.pack(side=tk.RIGHT, padx=5)
        
        # 日志区域
        ttk.Label(info_frame, text="操作日志:").pack(anchor=tk.W, padx=5, pady=5)
        self.log_text = scrolledtext.ScrolledText(info_frame, height=10, width=50)
        self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.log_text.insert(tk.END, "欢迎使用智能清理工具，请配置清理选项并开始扫描...\n")
        self.log_text.config(state=tk.DISABLED)
        
        # 扫描结果摘要
        ttk.Label(info_frame, text="扫描结果摘要:").pack(anchor=tk.W, padx=5, pady=5)
        self.result_text = scrolledtext.ScrolledText(info_frame, height=10, width=50)
        self.result_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.result_text.config(state=tk.DISABLED)
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        ttk.Label(self, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W).pack(side=tk.BOTTOM, fill=tk.X)

        # 配置LabelFrame样式
        style = ttk.Style()
        style.configure('Active.TLabelframe.Label', foreground='black')
        style.configure('Disabled.TLabelframe.Label', foreground='gray60')
        style.map('Active.TLabelframe.Label', foreground=[('active', 'black')])
        style.map('Disabled.TLabelframe.Label', foreground=[('active', 'gray60')])
        
        # 初始更新描述
        self.update_hash_description()
        self.toggle_duplicate_settings()
        self.toggle_package_settings()

    def toggle_duplicate_settings(self):
        """根据重复文件选择状态切换相关设置可用性"""
        enable = self.duplicate_var.get() == 1
        
        # 设置哈希算法区域状态
        self.algo_combobox.configure(state='readonly' if enable else 'disabled')
        self.hash_desc_label.configure(state=tk.NORMAL if enable else tk.DISABLED)
        
        # 设置文件夹扫描区域状态
        self.folder_check.configure(state=tk.NORMAL if enable else tk.DISABLED)
        self.depth_entry.configure(state=tk.NORMAL if enable else tk.DISABLED)

        
        # 设置快速模式区域状态
        self.fast_mode_check.configure(state=tk.NORMAL if enable else tk.DISABLED)

    def toggle_directory_controls(self, enable: bool):
        """切换目录相关控件的状态"""
        state = tk.NORMAL if enable else tk.DISABLED
        
        # 控制目录列表相关控件
        self.dir_listbox.config(state=state)
        self.add_dir_button.config(state=state)
        self.remove_dir_button.config(state=state)
        self.add_temp_button.config(state=state)
        
        # 控制全盘扫描选项
        if not enable:
            # 当禁用时强制取消全盘扫描
            self.full_scan.set(False)
            self.toggle_full_scan()
        
    def toggle_package_settings(self):
        """根据软件包选择状态切换相关设置可用性"""
        enable = self.package_var.get() == 1
        
        # 设置扩展名区域状态
        self.ext_entry.configure(state=tk.NORMAL if enable else tk.DISABLED)
    
    def update_hash_description(self, event=None):
        """更新哈希算法描述"""
        algorithms = CleanerConfig.get_hash_algorithms()
        selected = self.hash_algorithm_var.get()
        desc = f"速度: {algorithms[selected]['speed']}, 安全性: {algorithms[selected]['security']}"
        self.hash_desc_var.set(desc)

    def apply_filter_settings(self):
        if not hasattr(self, 'manager'):
            messagebox.showwarning("警告", "请先开始扫描以初始化配置")
            return
        
        # 从 UI 组件获取过滤参数
        keywords = self.keyword_entry.get().split(',')
        logic = "or" if self.logic_combobox.get() == "或 (OR)" else "and"
        recursive = self.recursive_var.get()
        exclude_exts = self.exclude_ext_entry.get().split(',')
        
        # 应用到管理器的配置对象
        self.manager.config.set_keyword_filters(keywords, logic, recursive)
        self.manager.config.set_exclude_extensions(exclude_exts)
        self.manager.config.recursive = self.recursive_var.get()

    def toggle_full_scan(self):
        """切换全盘扫描模式"""
        if self.full_scan.get():
            # 启用全盘扫描时，禁用目录列表
            self.dir_listbox.config(state=tk.DISABLED)
            self.add_dir_button.config(state=tk.DISABLED)
            self.remove_dir_button.config(state=tk.DISABLED)
            self.add_temp_button.config(state=tk.DISABLED)
        else:
            # 禁用全盘扫描时，启用目录列表
            self.dir_listbox.config(state=tk.NORMAL)
            self.add_dir_button.config(state=tk.NORMAL)
            self.remove_dir_button.config(state=tk.NORMAL)
            self.add_temp_button.config(state=tk.NORMAL)
    
    def add_directory(self):
        """添加自定义扫描目录"""
        if self.full_scan.get():
            messagebox.showinfo("提示", "全盘扫描模式下无法添加自定义目录")
            return

        # 显示内存使用情况
        self.update_log(f"当前内存使用: {psutil.virtual_memory().percent}%")

        dir_path = filedialog.askdirectory(title="选择扫描目录")
        if dir_path and dir_path not in self.custom_dirs:
            self.custom_dirs.append(dir_path)
            self.dir_listbox.insert(tk.END, dir_path)
            self.save_settings()

    def clear_duplicate_result(self):
        """清除重复文件结果设置"""
        self.duplicate_result_file.set("")
        self.save_settings()
        # 清除结果后启用目录选择
        self.toggle_directory_controls(True)
    
    def remove_directory(self):
        """删除选中的扫描目录"""
        if self.full_scan.get():
            messagebox.showinfo("提示", "全盘扫描模式下无法删除目录")
            return
            
        selected = self.dir_listbox.curselection()
        if selected:
            index = selected[0]
            del self.custom_dirs[index]
            self.dir_listbox.delete(index)
            self.save_settings()
    
    def add_system_temp_dirs(self):
        """添加系统临时目录到扫描列表"""
        if self.full_scan.get():
            messagebox.showinfo("提示", "全盘扫描模式下已包含系统临时目录")
            return
            
        # 先检测系统类型
        system_type = self.get_system_type() or CleanerConfig()._detect_system()
        
        # 获取系统临时目录
        config = CleanerConfig(system_type)
        temp_dirs = config.platform_config.get('temp_dirs', [])
        
        # 添加到列表中
        added_count = 0
        for dir_path in temp_dirs:
            if os.path.exists(dir_path) and dir_path not in self.custom_dirs:
                self.custom_dirs.append(dir_path)
                self.dir_listbox.insert(tk.END, dir_path)
                added_count += 1
        
        if added_count > 0:
            self.update_log(f"已添加 {added_count} 个系统临时目录")
            self.save_settings()
        else:
            self.update_log("没有可添加的系统临时目录")
    
    def get_system_type(self):
        """获取用户选择的系统类型"""
        user_input = self.system_combobox.get().lower()
        if user_input == "自动检测":
            return None
        return {"windows": "windows", "linux": "linux", "macos": "macos"}.get(user_input, "windows")
    
    def update_progress(self, value):
        """更新进度条"""
        self.progress_bar['value'] = value
        self.status_var.set(f"扫描进度: {value:.1f}%")
    
    def start_scan(self):
        """开始扫描过程"""
        if self.is_scanning:
            return
            
        # 更新清理类型选择
        self.clean_types = []
        if self.duplicate_var.get() == 1:
            self.clean_types.append("duplicate")
        if self.package_var.get() == 1:
            self.clean_types.append("package")
            
        if not self.clean_types:
            messagebox.showwarning("错误", "请至少选择一种清理类型")
            return

        self.system_type = self.get_system_type()
        
        # 确认全盘扫描
        if self.full_scan.get():
            if not messagebox.askyesno("确认全盘扫描", "全盘扫描会检查系统所有驱动器，可能需要较长时间并需要管理员权限。是否继续？"):
                return
        
        # 准备扫描目录
        scan_dirs = self.custom_dirs if not self.full_scan.get() else []
        
        try:
            self.manager = CleanManager(
                system_type=self.system_type,
                clean_dirs=scan_dirs,
                link_type='delete',
                full_scan=self.full_scan.get(),
                fast_mode=self.fast_mode_var.get(),
                hash_algorithm=self.hash_algorithm_var.get()
            )
            
            # 应用过滤设置
            self.apply_filter_settings()

            # 设置高级选项
            self.manager.config.check_folders = self.check_folders.get()
            self.manager.config.folder_depth = self.folder_depth.get()
            self.manager.config.recursive = self.recursive_var.get()

            
            # 设置重复文件扫描结果文件（如果有）
            if self.duplicate_var.get() == 1 and self.duplicate_result_file.get():
                self.manager.cleaners['duplicate'].duplicate_result_file = self.duplicate_result_file.get()
            
            # 添加自定义扩展名
            custom_exts = self.ext_entry.get().split(',')
            custom_exts = [ext.strip().lower() for ext in custom_exts if ext.strip()]
            self.manager.config.add_custom_extensions(custom_exts)
            
            self.update_log("开始扫描...")
            if self.full_scan.get():
                self.update_log("🔍 正在进行全盘扫描，请耐心等待...")
                self.update_log(f"内存保护阈值: {self.manager.config.memory_threshold}%")
            else:
                self.update_log(f"🔍 正在扫描指定目录: {', '.join(scan_dirs) if scan_dirs else '默认目录'}")
            
            self.progress_bar['value'] = 0
            self.show_results_button.config(state=tk.DISABLED)
            self.clean_button.config(state=tk.DISABLED)
            self.start_button.config(state=tk.DISABLED)
            self.stop_button.config(state=tk.NORMAL)
            self.pause_button.config(state=tk.NORMAL)
            self.is_scanning = True
            self.scan_paused = False
            
            # 清空结果区域
            self.result_text.config(state=tk.NORMAL)
            self.result_text.delete(1.0, tk.END)
            self.result_text.config(state=tk.DISABLED)
            
            # 在单独的线程中运行扫描，避免阻塞UI
            scan_thread = threading.Thread(target=self.run_scan_in_thread)
            scan_thread.name = "ScanThread-Main"
            scan_thread.daemon = True
            scan_thread.start()
            
        except Exception as e:
            error_msg = f"扫描初始化失败: {str(e)}"
            messagebox.showerror("错误", error_msg)
            self.update_log(f"❌ {error_msg}")
            self.is_scanning = False
            self.reset_ui_after_scan()
    
    def run_scan_in_thread(self):
        """在单独的线程中运行扫描"""
        current_thread = threading.current_thread()
        try:
            # 创建线程安全的日志回调
            def thread_safe_log(message):
                self.after(0, lambda: self.update_log(message))
            
            self.manager.run_scan(
                self.clean_types, 
                self.update_progress,
                thread_safe_log  # 传递日志回调
            )
            
            # 扫描完成后弹出确认框
            self.after(0, lambda: messagebox.showinfo("扫描结束", "扫描已完成！"))
            self.after(0, self.update_results_after_scan)

        except KeyboardInterrupt:
            print(f"Thread {current_thread.name} received KeyboardInterrupt")
            
        except Exception as e:
            error_msg = f"扫描失败: {str(e)}"
            print(f"Thread {current_thread.name} failed: {error_msg}")
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
            self.after(0, lambda: self.update_log(f"❌ {error_msg}"))
        finally:
            self.after(0, self.reset_ui_after_scan)
    
    def reset_ui_after_scan(self):
        """扫描完成后重置UI状态"""
        self.start_button.config(state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)
        self.pause_button.config(state=tk.DISABLED)
        self.is_scanning = False
        self.scan_paused = False
        self.status_var.set("就绪")

    def browse_duplicate_result_file(self):
        """浏览并选择重复文件扫描结果文件"""
        file_path = filedialog.askopenfilename(
            title="选择重复文件扫描结果",
            filetypes=[("JSON files", "*.json")]
        )
        if file_path:
            self.duplicate_result_file.set(file_path)
    
    def update_results_after_scan(self):
        """更新扫描结果显示"""
        scan_result = self.get_scan_result_text()
        self.result_text.config(state=tk.NORMAL)
        self.result_text.insert(tk.END, scan_result)
        self.result_text.config(state=tk.DISABLED)

        self.update_log("扫描完成，可点击'查看扫描结果'查看详情")
        self.show_results_button.config(state=tk.NORMAL)
        self.clean_button.config(state=tk.NORMAL)
        self.progress_bar['value'] = 100
    
    def stop_scan(self):
        """停止正在进行的扫描"""
        if self.is_scanning and hasattr(self, 'manager'):
            self.manager.stop_scan()
            self.scan_paused = False
            self.pause_button.config(state=tk.DISABLED, text="暂停")
            self.status_var.set("扫描已停止")
            self.update_log("正在停止扫描...")
    
    def toggle_pause(self):
        """切换扫描暂停状态"""
        if hasattr(self, 'manager'):
            if self.scan_paused:
                self.manager.resume_scan()
                self.pause_button.config(text="暂停")
                self.status_var.set("扫描中...")
                self.scan_paused = False
            else:
                self.manager.pause_scan()
                self.pause_button.config(text="继续")
                self.status_var.set("扫描已暂停")
                self.scan_paused = True
            self.update_log(f"扫描已{'暂停' if self.scan_paused else '继续'}")
    
    def get_scan_result_text(self):
        """获取扫描结果的文本摘要"""
        scan_result_text = ""
        for clean_type, path in getattr(self, 'manager', {}).scan_data.items():
            try:
                # 规范化路径
                norm_path = os.path.normpath(path)
                with open(norm_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    if clean_type == "duplicate":
                        groups = data.get('groups', [])
                        duplicate_count = sum(len(group['files']) - 1 for group in groups)
                        total_size = sum(group.get('total_size', 0) for group in groups)
                        scan_result_text += f"重复文件扫描结果：发现 {duplicate_count} 个重复文件，可释放 {total_size/1024/1024:.2f} MB\n"
                        
                        folder_groups = data.get('folder_groups', [])
                        if folder_groups:
                            folder_count = sum(len(group['folders']) - 1 for group in folder_groups)
                            folder_size = sum(group.get('total_size', 0) for group in folder_groups)
                            scan_result_text += f"重复文件夹扫描结果：发现 {folder_count} 个重复文件夹，可释放 {folder_size/1024/1024:.2f} MB\n"
                    elif clean_type == "package":
                        package_files = data.get('files', [])
                        package_count = len(package_files)
                        total_size = sum(item.get('size', 0) for item in package_files if isinstance(item, dict))
                        scan_result_text += f"软件包扫描结果：发现 {package_count} 个软件包，可释放 {total_size/1024/1024:.2f} MB\n"
            except Exception as e:
                error_msg = f"无法读取{clean_type}扫描结果: {str(e)}"
                scan_result_text += error_msg + "\n"
                self.update_log(f"❌ {error_msg}")
        return scan_result_text
    
    def show_scan_results(self):
        """显示扫描结果详情"""
        if not hasattr(self, 'manager') or not self.manager.scan_data:
            messagebox.showinfo("提示", "没有扫描结果可供显示")
            return
            
        for clean_type, path in self.manager.scan_data.items():
            try:
                # 规范化路径
                norm_path = os.path.normpath(path)
                with open(norm_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    EnhancedScanResultsWindow(self, clean_type, data, self)
            except Exception as e:
                error_msg = f"无法显示{clean_type}扫描结果: {str(e)}"
                messagebox.showerror("错误", error_msg)
                self.update_log(f"❌ {error_msg}")
    
    def load_scan_results(self):
        import traceback
        file_path = filedialog.askopenfilename(
            title="选择扫描结果文件",
            filetypes=[("JSON files", "*.json")],
            initialdir="scan_results"
        )
        
        if not file_path:
            return
            
        try:
            file_path = str(Path(file_path).resolve())
            
            if not Path(file_path).exists():
                raise FileNotFoundError(f"路径不存在: {file_path}")
            if not Path(file_path).is_file():
                raise IsADirectoryError(f"路径是目录: {file_path}")
            if not os.access(file_path, os.R_OK):
                raise PermissionError(f"无读取权限: {file_path}")

            if not os.path.isfile(file_path):
                raise ValueError("文件路径无效或文件不存在")
                
            with open(file_path, 'r', encoding='utf-8') as f:
                 raw_content = f.read()
                 data = json.loads(raw_content)
                
                 def normalize_paths(obj):
                    if isinstance(obj, dict):
                        for key in list(obj.keys()):
                            if key == 'path' and isinstance(obj[key], str):
                                # 保留原始路径，不转换为绝对路径
                                obj[key] = obj[key]
                            elif key == 'folders' and isinstance(obj[key], list):
                                # 处理文件夹列表：仅规范化路径格式（保留原始字符串）
                                obj[key] = [str(Path(p)) for p in obj[key]]
                            elif key == 'files' and isinstance(obj[key], list):
                                # 处理文件列表：保留原始路径
                                new_files = []
                                for f in obj[key]:
                                    if isinstance(f, dict) and 'path' in f:
                                        f['path'] = str(Path(f['path']))  # 规范化但不解析为绝对路径
                                    new_files.append(f)
                                obj[key] = new_files
                            elif key == 'groups' and isinstance(obj[key], list):
                                # 处理重复文件组
                                new_groups = []
                                for group in obj[key]:
                                    if 'files' in group and isinstance(group['files'], list):
                                        group['files'] = [str(Path(fp)) for fp in group['files']]
                                    new_groups.append(group)
                                obj[key] = new_groups
                            else:
                                normalize_paths(obj[key])
                    elif isinstance(obj, list):
                        for item in obj:
                            normalize_paths(item)
                 
                 normalize_paths(data)
                 
                 def fix_timestamps(obj):
                    if isinstance(obj, dict):
                        if 'mtime' in obj:
                            try:
                                obj['mtime'] = float(obj['mtime'])
                            except (TypeError, ValueError):
                                obj['mtime'] = datetime.now().timestamp()
                        for v in obj.values():
                            fix_timestamps(v)
                    elif isinstance(obj, list):
                        for item in obj:
                            fix_timestamps(item)
                 fix_timestamps(data)
            
            scan_type = data.get('scan_type', '未知类型')
            self.display_scan_results(scan_type, data, file_path)
            
        except Exception as e:
                error_msg = (
                    f"加载失败详情：\n"
                    f"错误类型: {type(e).__name__}\n"
                    f"错误信息: {str(e)}\n"
                    f"文件路径: {file_path}\n"
                    f"文件大小: {Path(file_path).stat().st_size if Path(file_path).exists() else 0} 字节\n"
                    f"堆栈跟踪:\n{traceback.format_exc()}"
                )
                messagebox.showerror("严重错误", error_msg)
                self.update_log(f"❌ 加载失败详细信息:\n{error_msg}")

    def display_scan_results(self, scan_type: str, data: dict, file_path: str):
        """独立封装结果显示逻辑"""
        self.result_text.config(state=tk.NORMAL)
        self.result_text.delete(1.0, tk.END)
        
        if scan_type == "duplicate":
            self.display_duplicate_results(data)
        elif scan_type == "package":
            self.display_package_results(data)
            
        self.result_text.config(state=tk.DISABLED)
        EnhancedScanResultsWindow(self, scan_type, data, self)
        self.update_log(f"已加载历史扫描结果：{os.path.basename(file_path)}")
        self.show_results_button.config(state=tk.NORMAL)
        self.clean_button.config(state=tk.NORMAL)
    

    def display_duplicate_results(self, data: dict):
        """显示重复文件/文件夹结果"""
        groups = data.get('groups', [])
        duplicate_count = sum(len(group['files']) - 1 for group in groups)
        total_size = sum(group.get('total_size', 0) for group in groups)
        self.result_text.insert(tk.END, f"重复文件扫描结果：发现 {duplicate_count} 个重复文件，可释放 {total_size/1024/1024:.2f} MB\n")
        
        folder_groups = data.get('folder_groups', [])
        if folder_groups:
            folder_count = sum(len(group['folders']) - 1 for group in folder_groups)
            folder_size = sum(group.get('total_size', 0) for group in folder_groups)
            self.result_text.insert(tk.END, f"重复文件夹扫描结果：发现 {folder_count} 个重复文件夹，可释放 {folder_size/1024/1024:.2f} MB\n")

    def display_package_results(self, data: dict):
        """显示软件包结果（严格过滤无效数据）"""
        package_files = [item for item in data.get('files', []) if isinstance(item, dict)]
        valid_files = [item for item in package_files if os.path.exists(item.get('path', ''))]
        package_count = len(valid_files)
        total_size = sum(item.get('size', 0) for item in valid_files)

        for item in valid_files:
            if not Path(item['path']).exists():
                self.update_log(f"⚠️ 警告：文件不存在 {item['path']}")
                valid_files.remove(item)

        self.result_text.insert(tk.END, f"软件包扫描结果：发现 {package_count} 个软件包，可释放 {total_size/1024/1024:.2f} MB\n")
    
    def start_clean(self):
        """开始清理过程"""
        if not hasattr(self, 'manager') or not self.manager.scan_data:
            messagebox.showinfo("提示", "没有扫描结果可供清理")
            return
            
        self.do_clean = True
        try:
            self.update_log("开始清理...")
            self.progress_bar['value'] = 0
            self.start_button.config(state=tk.DISABLED)
            self.show_results_button.config(state=tk.DISABLED)
            self.clean_button.config(state=tk.DISABLED)
            self.pause_button.config(state=tk.DISABLED)
            
            # 在单独的线程中运行清理
            clean_thread = threading.Thread(target=self.run_clean_in_thread)
            clean_thread.daemon = True
            clean_thread.start()
            
        except Exception as e:
            error_msg = f"清理失败: {str(e)}"
            messagebox.showerror("错误", error_msg)
            self.update_log(f"❌ {error_msg}")
            self.reset_ui_after_clean()
    
    def run_clean_in_thread(self):
        """在单独的线程中运行清理"""
        try:
            cleaned_count = self.manager.run_clean(self.clean_types)
            
            # 更新UI
            self.after(0, lambda: self.update_log(f"清理完成！共清理 {cleaned_count} 个项目"))
            self.after(0, lambda: messagebox.showinfo("清理完成", f"已成功清理 {cleaned_count} 个项目"))
            
            # 更新结果显示
            self.after(0, self.update_results_after_clean)
            
        except Exception as e:
            error_msg = f"清理失败: {str(e)}"
            self.after(0, lambda: messagebox.showerror("错误", error_msg))
            self.after(0, lambda: self.update_log(f"❌ {error_msg}"))
        finally:
            self.after(0, self.reset_ui_after_clean)
    
    def reset_ui_after_clean(self):
        """清理完成后重置UI状态"""
        self.start_button.config(state=tk.NORMAL)
        self.progress_bar['value'] = 0
        self.pause_button.config(state=tk.DISABLED)
        self.scan_paused = False
        self.status_var.set("就绪")
    
    def update_results_after_clean(self):
        """清理后更新结果显示"""
        scan_result = self.get_scan_result_text()
        self.result_text.config(state=tk.NORMAL)
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, scan_result)
        self.result_text.config(state=tk.DISABLED)
        
        self.show_results_button.config(state=tk.NORMAL)
    
    def save_settings(self):
        """保存当前设置"""
        try:
            settings = {
                'system_type': self.system_combobox.get(),
                'custom_dirs': self.custom_dirs,
                'duplicate_enabled': self.duplicate_var.get() == 1,
                'package_enabled': self.package_var.get() == 1,
                'check_folders': self.check_folders.get(),
                'folder_depth': self.folder_depth.get(),
                'package_exts': self.ext_entry.get(),
                'full_scan': self.full_scan.get(),
                'include_keywords': self.keyword_entry.get().split(','),
                'keyword_logic': "or" if self.logic_combobox.get() == "或 (OR)" else "and",
                'recursive': self.recursive_var.get(),
                'exclude_exts': self.exclude_ext_entry.get().split(','),
                'hash_algorithm': self.hash_algorithm_var.get(),
                'duplicate_result': self.duplicate_result_file.get(),
            }
            
            with open('cleaner_settings.json', 'w', encoding='utf-8') as f:
                json.dump(settings, f, indent=2)
        except Exception as e:
            error_msg = f"保存设置失败: {e}"
            print(error_msg)
            self.update_log(f"❌ {error_msg}")
    
    def load_settings(self):
        """加载上次保存的设置"""
        try:
            if os.path.exists('cleaner_settings.json'):
                with open('cleaner_settings.json', 'r', encoding='utf-8') as f:
                    settings = json.load(f)
                    
                    if 'system_type' in settings:
                        self.system_combobox.set(settings['system_type'])
                    
                    if 'custom_dirs' in settings:
                        self.custom_dirs = settings['custom_dirs']
                        for dir_path in self.custom_dirs:
                            self.dir_listbox.insert(tk.END, dir_path)
                    
                    if 'duplicate_enabled' in settings:
                        self.duplicate_var.set(1 if settings['duplicate_enabled'] else 0)
                    
                    if 'package_enabled' in settings:
                        self.package_var.set(1 if settings['package_enabled'] else 0)
                    
                    if 'check_folders' in settings:
                        self.check_folders.set(settings['check_folders'])
                    
                    if 'folder_depth' in settings:
                        self.folder_depth.set(settings['folder_depth'])
                    
                    if 'package_exts' in settings:
                        self.ext_entry.delete(0, tk.END)
                        self.ext_entry.insert(0, settings['package_exts'])

                    if 'duplicate_result' in settings:
                        self.duplicate_result_file.set(settings['duplicate_result'])
                        # 如果设置了结果文件，则禁用目录控件
                        self.toggle_directory_controls(not bool(settings['duplicate_result']))
                    
                    if 'full_scan' in settings:
                        self.full_scan.set(settings['full_scan'])
                        self.toggle_full_scan()

                    if 'fast_mode' in settings:
                        self.fast_mode_var.set(settings['fast_mode'])

                    if 'include_keywords' in settings:
                        self.keyword_entry.delete(0, tk.END)
                        self.keyword_entry.insert(0, ",".join(settings['include_keywords']))
                    if 'keyword_logic' in settings:
                        self.logic_combobox.set("或 (OR)" if settings['keyword_logic'] == "or" else "与 (AND)")
                    if 'recursive' in settings:
                        self.recursive_var.set(settings['recursive'])
                    if 'exclude_exts' in settings:
                        self.exclude_ext_entry.delete(0, tk.END)
                        self.exclude_ext_entry.insert(0, ",".join(settings['exclude_exts']))
                    if 'hash_algorithm' in settings:
                        self.hash_algorithm_var.set(settings['hash_algorithm'])
        except Exception as e:
            error_msg = f"加载设置失败: {e}"
            print(error_msg)
            self.update_log(f"❌ {error_msg}")